package com.mark.common.utils;

import com.aliyun.oss.OSSClient;
import com.aliyun.oss.model.PutObjectResult;
import com.google.common.collect.Maps;
import com.mark.common.exception.Campuso2oException;
import com.mark.common.exception.ImageException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.util.Date;
import java.util.Map;
import java.util.Random;

/**
 * @Description: 路径处理工具类
 * @Author: Mark
 * @CreateDate: 2018/9/28 8:54
 * @Version: 2.0
 * @Copyright : 豆浆油条个人非正式工作室
 */
@Slf4j
public class OSSClientUtil {

    private static String endpoint = "oss-cn-beijing.aliyuncs.com";
    private static String accssKeyId = "LTAIJ2l3xNEN83ZX";
    private static String accessKeySeccret = "Tazi7kaUVNlJAngXXF0tsz28F9iIMB";
    private static String bucketName = "campuso2o";
    //存放文件的根目录
    private static String fileDir = "image";
    private static OSSClient ossClient;

    private static final Integer MAX_SIZE = 10 * 1024 * 1024;

    /**
     * 构造函数私有化，不允许外部创建该类的实例
     */
    private OSSClientUtil(){ }

    /**
     * 饿汉模式创建单例对象
     */
    static {
        ossClient = new OSSClient(endpoint, accssKeyId, accessKeySeccret);
    }

    /*****对外开放的接口*************************************************************************************************************/
    public static void uploadImg2Oss(String url){
        File fileOnServer = new File(url);
        FileInputStream fileInputStream;
        try{
            fileInputStream = new FileInputStream(fileOnServer);
            String[] split = url.split("/");
            uploadFile2OSS(fileInputStream,split[split.length - 1]);
        }catch (Exception e){

        }
    }

    /**
     * 对开方法的接口：上传图片到OSS
     * @param multipartFile ：文件
     * @param imageRole ：图片的角色，比如存放用户、商品、公告的图片
     * @param roleId ：图片的角色id
     * @return ：返回存放到OSS服务中的相对路径，该值存放到数据库中
     */
    public static String uploadImg2Oss(MultipartFile multipartFile,String imageRole ,Integer roleId)  {
        //参数校验
        if(multipartFile == null) {
            throw new ImageException("上传的文件不能为空！");
        }
        if (multipartFile.getSize() > MAX_SIZE) {
            throw new ImageException("上传的图片大小不能超过10M！");
        }
        if(StringUtils.isBlank(imageRole)){
            throw new ImageException("输入的图片所属类型不能为空！");
        }
        if(roleId == null){
            throw new ImageException("输入的类型ID不能为空！");
        }

        Map<String, Object> resultMap = getNewName(multipartFile, imageRole, roleId);
        String relativePath = (String) resultMap.get("relativePath");
        multipartFile = (MultipartFile) resultMap.get("file");
        try {
            InputStream inputStream = multipartFile.getInputStream();
            uploadFile2OSS(inputStream, relativePath);
            Date expiration = new Date(System.currentTimeMillis() + 3600L * 1000 * 24 * 365 * 10);
            return ossClient.generatePresignedUrl(bucketName, relativePath, expiration).toString();
        } catch (Exception e) {
            throw new ImageException("上传图片到OSS服务器异常" + e.getMessage());
        }finally {
            //图片压缩后的路径
            String locationPath = (String) resultMap.get("locationPath");
            if(StringUtils.isNotBlank(locationPath)){
                File file = new File(locationPath);
                if(file.exists()){
                    file.delete();
                }
            }
        }
    }

    /*************************************私有方法**********************************************************************/
    /**
     * 获取存储在OSS服务文件的相对路径
     * @param multipartFile
     * @param imageRole
     * @param roleId
     * @return
     */
    private static Map<String,Object> getNewName(MultipartFile multipartFile, String imageRole, Integer roleId) {
        //对待上传的文件进行压缩处理
        //图片压缩后的绝对路径
        String locationPath = null;
        if(!StringUtils.equals("qr",imageRole)){
            Map<String,Object> resultMap= ImageUtil.generateThumbnail(multipartFile, imageRole);
            multipartFile = (MultipartFile) resultMap.get("file");
            locationPath = (String) resultMap.get("location");
        }
        String originalFilename = multipartFile.getOriginalFilename();
        if (StringUtils.isBlank(originalFilename)) {
            originalFilename = multipartFile.getName();
            if(StringUtils.isBlank(originalFilename)) {
                throw new Campuso2oException("上传文件的原文件名不能为空");
            }else if(!originalFilename.contains(".")){
                throw new Campuso2oException("上传的文件的原始文件名不正确不含有.");
            }

        }
        String fileExtensionName = originalFilename.substring(originalFilename.lastIndexOf(".")).toLowerCase();
        Random random = new Random();
        String newName = random.nextInt(10000) + System.currentTimeMillis() + fileExtensionName;
        StringBuilder relativePath = new StringBuilder();
        relativePath.append(fileDir);
        relativePath.append("/");
        relativePath.append(imageRole);
        relativePath.append("/");
        relativePath.append(roleId.toString());
        relativePath.append("/");
        relativePath.append(newName);

        Map<String, Object> resultMap = Maps.newHashMap();
        resultMap.put("relativePath", relativePath.toString());
        resultMap.put("file", multipartFile);
        resultMap.put("locationPath", locationPath);
        return resultMap;
    }


    /**     * Description: 判断OSS服务文件上传时文件的contentType
     *
     * @param filenameExtension
     *            文件后缀
     * @return String
     */
    private static String getContentType(String filenameExtension) {
        if (filenameExtension.equalsIgnoreCase("bmp")) {
            return "image/bmp";
        }
        if (filenameExtension.equalsIgnoreCase("gif")) {
            return "image/gif";
        }
        if (filenameExtension.equalsIgnoreCase("jpeg") || filenameExtension.equalsIgnoreCase("jpg")
                || filenameExtension.equalsIgnoreCase("png")) {
            return "image/jpeg";
        }
        if (filenameExtension.equalsIgnoreCase("html")) {
            return "text/html";
        }
        if (filenameExtension.equalsIgnoreCase("txt")) {
            return "text/plain";
        }
        if (filenameExtension.equalsIgnoreCase("vsd")) {
            return "application/vnd.visio";
        }
        if (filenameExtension.equalsIgnoreCase("pptx") || filenameExtension.equalsIgnoreCase("ppt")) {
            return "application/vnd.ms-powerpoint";
        }
        if (filenameExtension.equalsIgnoreCase("docx") || filenameExtension.equalsIgnoreCase("doc")) {
            return "application/msword";
        }
        if (filenameExtension.equalsIgnoreCase("xml")) {
            return "text/xml";
        }
        return "image/jpeg";
    }

    private static void uploadFile2OSS(InputStream inStream, String relativePath) throws IOException {
        String ret = "";
        try {
            //上传文件
            PutObjectResult putResult = ossClient.putObject(bucketName, relativePath, inStream);
            ret = putResult.getETag();
        }catch (Exception e){
            log.error(e.getMessage(), e);
            throw e;
        }finally {
            if (inStream != null) {
                try {
                    inStream.close();
                } catch (IOException e) {
                    log.error("关闭文件流异常！");
                    throw e;
                }
            }
        }
    }

    public static void main(String[] args) throws IOException {

        File file = new File("C:\\Users\\Administrator\\Desktop\\test\\test.jpg");
        FileInputStream inputStream = new FileInputStream(file);
        MultipartFile multipartFile = new MockMultipartFile(file.getName(),file.getName(),"image/jpeg",inputStream);
        String user = new OSSClientUtil().uploadImg2Oss(multipartFile, "user", 1);
        System.out.println(user);

    }


}
